using System.Collections.Generic;
using System.Windows.Media;

namespace DrawToolsLib {
    /// <summary>
    /// Changing state of existing objects:
    /// move, resize, change properties.
    /// 
    /// This command is always applied to the list selection.
    /// It keeps selection clone before and after operation.
    /// Undo/Redo operations replace objects in the list
    /// using selection clone.
    /// </summary>
    class CommandChangeState : CommandBase {
        // Selected object(s) before operation
        List<GraphicsBase> oldList;

        // Selected object(s) after operation
        List<GraphicsBase> newList;


        // Create this command BEFORE operation.
        public CommandChangeState(DrawingCanvas drawingCanvas) {
            // Keep objects state before operation.
            FillList(drawingCanvas, ref oldList, ref newList);
        }

        /// <summary>
        /// Restore selection to its state before change.
        /// </summary>
        public override void Undo(DrawingCanvas drawingCanvas) {
            // Replace all objects in the listNew with objects from listOld
            ReplaceObjects(drawingCanvas, newList, oldList);
        }

        /// <summary>
        /// Restore selection to its state after change.
        /// </summary>
        public override void Redo(DrawingCanvas drawingCanvas) {
            // Replace all objects in the listOld with objects from listNew
            ReplaceObjects(drawingCanvas, oldList, newList);
        }

        /// <summary>
        /// Replace objects in graphicsList with objects from clone list
        /// </summary>
        /// <param name="d">Current DrawingCanvas</param>
        /// <param name="oldList">Current list to be replaced.</param>
        /// <param name="newList">New list to be applied.</param>
        private static void ReplaceObjects(DrawingCanvas d, List<GraphicsBase> oldList, List<GraphicsBase> newList) {
            int index;
            for (int i = 0; i < oldList.Count; i++) {
                index = d.GraphicsList.IndexOf(oldList[i]);
                // Replace object with its clone
                d.Pop(index);
                d.Push(index, newList[i]);
            }

            foreach (GraphicsBase g in d.GraphicsList) {
                g.IsSelected = (newList.Contains(g)) ? true : false;
            }
        }

        // Fill list from selection
        private static void FillList(DrawingCanvas d, ref List<GraphicsBase> oldList, ref List<GraphicsBase> newList) {
            oldList = new List<GraphicsBase>();
            newList = new List<GraphicsBase>();
            GraphicsBase oldg, newg;

            int count = d.GraphicsList.Count;
            for (int i = 0; i < count; i++) {
                if (((GraphicsBase)d.GraphicsList[i]).IsSelected) {
                    // keep old value and replace it by new clone value
                    oldg = (GraphicsBase)d.GraphicsList[i];
                    oldList.Add(oldg);
                    d.Pop(oldg);

                    newg = (GraphicsBase)oldg.Clone();
                    newList.Add(newg);
                    d.Push(i, newg);
                }
            }
        }
    }
}
